package com.caregiver.watch.business.care.service.impl;

import com.alibaba.fastjson2.JSON;
import com.caregiver.watch.business.care.enums.HeartRateResultEnum;
import com.caregiver.watch.business.care.helper.EcgHelper;
import com.caregiver.watch.business.care.model.vo.ActivityDataDetailVo;
import com.caregiver.watch.business.care.model.vo.ActivityDataVo;
import com.caregiver.watch.business.care.model.vo.ActivityDataVo.ActivityDurationStatistics;
import com.caregiver.watch.business.care.model.vo.ActivityDataVo.CalorieStatistics;
import com.caregiver.watch.business.care.model.vo.ActivityDataVo.StepsStatistics;
import com.caregiver.watch.business.care.model.vo.ActivityDataVo.StandTimeStatistics;
import com.caregiver.watch.business.care.model.vo.BloodOxygenDetailDataVo;
import com.caregiver.watch.business.care.model.vo.BloodOxygenDetailDataVo.BloodOxygenData;
import com.caregiver.watch.business.care.model.vo.BloodPressureDetailDataVo;
import com.caregiver.watch.business.care.model.vo.BloodPressureDetailDataVo.BloodPressureData;
import com.caregiver.watch.business.care.model.vo.EcgDetailDataVo;
import com.caregiver.watch.business.care.model.vo.EcgDetailDataVo.EcgDetailData;
import com.caregiver.watch.business.care.model.vo.HealthDataVo;
import com.caregiver.watch.business.care.model.vo.HeartRateDetailVo;
import com.caregiver.watch.business.care.model.vo.HeartRriDetailDataVo;
import com.caregiver.watch.business.care.model.vo.LocationDataVo;
import com.caregiver.watch.business.care.model.vo.SleepDetailVo;
import com.caregiver.watch.business.care.model.vo.SportDataDetailVo;
import com.caregiver.watch.business.care.model.vo.SportDataDetailVo.SportDataDetail;
import com.caregiver.watch.business.care.model.vo.SportDataDetailVo.SportDataRecord;
import com.caregiver.watch.business.care.model.vo.SportDataVo;
import com.caregiver.watch.business.care.model.vo.StressValueDetailDataVo;
import com.caregiver.watch.business.care.model.vo.StressValueDetailDataVo.StressValueDetailData;
import com.caregiver.watch.business.care.model.vo.TemperatureDetailDataVo;
import com.caregiver.watch.business.care.model.vo.TodaySportDataVo;
import com.caregiver.watch.business.care.model.vo.TraceVo;
import com.caregiver.watch.business.care.model.vo.WeekActivityDataVo;
import com.caregiver.watch.business.care.model.vo.WeekSleepDetailVo;
import com.caregiver.watch.business.care.service.HealthService;
import com.caregiver.watch.business.data.enums.SportTypeEnum;
import com.caregiver.watch.business.data.model.dto.HeartEcgDataAnalysisResp;
import com.caregiver.watch.business.data.model.dto.HeartRriDataAnalysisResp;
import com.caregiver.watch.business.data.model.dto.SleepCalculationData;
import com.caregiver.watch.business.data.model.po.HealthBaseData;
import com.caregiver.watch.business.data.model.po.HealthBloodOxygen;
import com.caregiver.watch.business.data.model.po.HealthBloodPressure;
import com.caregiver.watch.business.data.model.po.HealthDeviceLocation;
import com.caregiver.watch.business.data.model.po.HealthEcg;
import com.caregiver.watch.business.data.model.po.HealthHeartRate;
import com.caregiver.watch.business.data.model.po.HealthHeartRateVariability;
import com.caregiver.watch.business.data.model.po.HealthRri;
import com.caregiver.watch.business.data.model.po.HealthSleepDisplay;
import com.caregiver.watch.business.data.model.po.HealthTemperature;
import com.caregiver.watch.business.data.model.po.SportData;
import com.caregiver.watch.business.data.service.AlgorithmService;
import com.caregiver.watch.business.data.service.HealthDataQueryService;
import com.caregiver.watch.business.user.enums.BloodPressureStatusEnum;
import com.caregiver.watch.business.user.enums.EcgAnalysisResultEnum;
import com.caregiver.watch.business.user.enums.WeekDay;
import com.caregiver.watch.business.user.model.vo.UserHealthGoalVo;
import com.caregiver.watch.business.user.service.UserService;
import com.caregiver.watch.business.user.utils.UserInfoUtils;
import com.caregiver.watch.common.constant.NumberConstants;
import com.caregiver.watch.common.exception.business.BusinessException;
import com.caregiver.watch.common.utils.ObjectUtils;
import com.caregiver.watch.common.utils.collection.ListUtils;
import com.caregiver.watch.common.utils.number.BigDecimalUtils;
import com.caregiver.watch.common.utils.number.IntegerUtils;
import com.caregiver.watch.common.utils.time.DateUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.caregiver.watch.business.care.enums.HeartRateResultEnum.NO_RESULT;
import static com.caregiver.watch.business.data.common.DataConstant.CONTINUOUS_SPORT_INTERVAL_TIME;
import static com.caregiver.watch.common.constant.NumberConstants.BIG_DECIMAL_TEN_THOUSAND;
import static com.caregiver.watch.common.constant.NumberConstants.ONE;
import static com.caregiver.watch.common.constant.NumberConstants.SEVEN;
import static com.caregiver.watch.common.constant.NumberConstants.TWO;
import static com.caregiver.watch.common.constant.NumberConstants.ZERO;

/**
 * @Description: 用户健康数据
 * @Author 疆戟
 * @Date 2025/9/20 22:11
 * @Version 1.0
 */
@AllArgsConstructor
@Service
@Slf4j
public class HealthServiceImpl implements HealthService {

    private final HealthDataQueryService healthDataQueryService;
    private final AlgorithmService algorithmService;
    private final UserService userService;

    @Override
    public TodaySportDataVo getTodaySportData(String deviceUuid) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空");
        }
        // 获取用户ID
        Long userId = UserInfoUtils.getUserId();
        UserHealthGoalVo userHealthGoalVo = userService.queryUserHealthGoal(userId);
        // 获取用户今天运动基础健康数据
        HealthBaseData healthBaseData =
                healthDataQueryService.queryHealthBaseData(userId, deviceUuid);
        // 获取 运动时长
        return TodaySportDataVo.build(healthBaseData, userHealthGoalVo);
    }

    @Override
    public List<SportDataVo> getSportData(String deviceUuid) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空");
        }
        List<SportData> sportDatas = healthDataQueryService.queryTodaySportData(UserInfoUtils.getUserId(), deviceUuid);
        // 将数据根据类型进行分组
        Map<SportTypeEnum, List<SportData>> sportTypeToSportDataMap = ListUtils.groupingBy(sportDatas, data -> SportTypeEnum.parse(data.getSportType()));
        // 遍历数据 统计运动次数 数据在分钟级别内是连续的，且中断不能超过5分钟认为是同一次运动
        return Stream.of(SportTypeEnum.values()).map(sportType -> {
                    List<SportData> sportDataList = sportTypeToSportDataMap.get(sportType);
                    if (CollectionUtils.isEmpty(sportDataList)) {
                        return SportDataVo.build(sportType, BigDecimal.ZERO, ZERO, ZERO);
                    }
                    int count = ZERO;
                    // 运行时间
                    int duration = ZERO;
                    BigDecimal distance = BigDecimal.ZERO;
                    LocalDateTime endTime = null;
                    for (SportData data : sportDataList) {
                        if (data == null || data.getDataTime() == null || data.getDistance() == null) {
                            continue; // 跳过无效数据
                        }
                        // 累计距离
                        distance = distance.add(data.getDistance());
                        if (Objects.nonNull(endTime)) {
                            long minutes = DateUtils.getTimeBetween(endTime, data.getDataTime(), TimeUnit.MINUTES);
                            // 间隔时间超过5分钟 累计运动次数
                            if (minutes >= CONTINUOUS_SPORT_INTERVAL_TIME) {
                                count++;
                            } else {
                                duration += minutes;
                            }
                            endTime = data.getDataTime();
                        } else {
                            endTime = data.getDataTime();
                            count++;
                        }
                    }
                    return SportDataVo.build(sportType, distance, duration, count);
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @Override
    public LocationDataVo getLocationData(String deviceUuid) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空");
        }
        // 获取用户ID
        Long userId = UserInfoUtils.getUserId();
        HealthDeviceLocation location = healthDataQueryService.queryLatestDeviceLocationByDeviceUuid(userId, deviceUuid);
        if (Objects.isNull( location)) {
            return null;
        }
        return LocationDataVo.build(location.getLongitude(), location.getLatitude(), location.getTrackDataTime());
    }

    @Override
    public TraceVo queryTrace(String deviceUuid, String startTime, String endTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空");
        }
        if (StringUtils.isBlank(startTime)) {
            throw new BusinessException("开始时间不能为空");
        }
        if (StringUtils.isBlank(endTime)) {
            throw new BusinessException("结束时间不能为空");
        }
        Long userId = UserInfoUtils.getUserId();
        // 将开始时间和结束时间转换为LocalDateTime
        LocalDateTime start = DateUtils.parseLocalDateTime(startTime);
        LocalDateTime end = DateUtils.parseLocalDateTime(endTime);
        log.info("deviceUuid:{} 开始时间:{} 结束时间:{}", deviceUuid, start, end);
        List<HealthDeviceLocation> locations = healthDataQueryService.queryDeviceLocations(userId, deviceUuid, start, end);
        log.info("deviceUuid :{} 轨迹数据:{}", deviceUuid, locations);
        return TraceVo.build(ListUtils.map(locations, location -> LocationDataVo.build(location.getLongitude(), location.getLatitude(), location.getTrackDataTime())));
    }

    @Override
    public HealthDataVo getHealthData(String deviceUuid) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空");
        }
        Long userId = UserInfoUtils.getUserId();
        HealthDataVo healthDataVo = new HealthDataVo();
        healthDataVo.setDeviceUuid(deviceUuid);
        healthDataVo.setUserId(userId);
        // 查询睡眠数据
        HealthSleepDisplay healthSleep = healthDataQueryService.queryLatestSleepData(userId, deviceUuid);
        if (Objects.nonNull(healthSleep)) {
            // 计算睡眠时长 单位是分钟
            LocalDateTime sleepDateTime = healthSleep.getStartTime();
            LocalDateTime wakeUpDateTime = healthSleep.getEndTime();
            healthDataVo.setSleepDuration(DateUtils.getTimeBetween(sleepDateTime, wakeUpDateTime, TimeUnit.MINUTES));
        }
        // 查询心率数据
        HealthHeartRate healthHeartRate = healthDataQueryService.queryLatestHrData(userId, deviceUuid);
        if (Objects.nonNull(healthHeartRate)) {
            healthDataVo.setHeartRate(healthHeartRate.getAvgBpm());
            healthDataVo.setHeartRateTime(healthHeartRate.getRecordedAt());
        }
        // 查询心电数据
        List<HealthEcg> healthEcgList = healthDataQueryService.queryLatestEcgData(userId, deviceUuid);
        // 获取心电数据
        HeartEcgDataAnalysisResp heartEcgDataAnalysisResp = algorithmService.heartDataAnalysis(deviceUuid, healthEcgList);
        if (Objects.nonNull(heartEcgDataAnalysisResp)) {
            healthDataVo.setHeartHealth(EcgAnalysisResultEnum.parse(heartEcgDataAnalysisResp.getResult()));
            ListUtils.ofNullable(healthEcgList, new ArrayList<>()).stream().findFirst().ifPresent(healthEcg -> healthDataVo.setEcgTime(healthEcg.getRecordedAt()));
        }
        // 查询血压数据
        HealthBloodPressure healthBloodPressure = healthDataQueryService.queryLatestBpData(userId, deviceUuid);
        if (Objects.nonNull(healthBloodPressure)) {
            healthDataVo.setSystolic(healthBloodPressure.getSystolic());
            healthDataVo.setDiastolic(healthBloodPressure.getDiastolic());
            healthDataVo.setBloodPressureTime(healthBloodPressure.getRecordedAt());
        }
        // 查询心率变异与疲劳数据
        HealthHeartRateVariability healthHeartRateVariability = healthDataQueryService.queryLatestHrvData(userId, deviceUuid);
        if (Objects.nonNull(healthHeartRateVariability)) {
            healthDataVo.setStressValue(healthHeartRateVariability.getStress());
            healthDataVo.setStressTime(healthHeartRateVariability.getRecordedAt());
        }
        // 血氧
        HealthBloodOxygen healthBloodOxygen = healthDataQueryService.queryLatestBloodOxygenData(userId, deviceUuid);
        if (Objects.nonNull(healthBloodOxygen)) {
            healthDataVo.setBloodOxygen(healthBloodOxygen.getAvgOxygen());
            healthDataVo.setBloodOxygenTime(healthBloodOxygen.getRecordedAt());
        }
        // 体温
        HealthTemperature healthTemperature =healthDataQueryService.queryLatestBodyTemperatureData(userId, deviceUuid);
        if (Objects.nonNull(healthTemperature)) {
            healthDataVo.setBodyTemperature(Optional.ofNullable(healthTemperature.getEstTemp()).map(temp -> temp.divide(BIG_DECIMAL_TEN_THOUSAND, ONE)).orElse(BigDecimal.ZERO));
            healthDataVo.setBodyTemperatureTime(healthTemperature.getRecordedAt());
        }
        return healthDataVo;
    }

    @Override
    public SleepDetailVo getSleepDetailData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate data = DateUtils.parseLocalDate(dataTime);
        if (Objects.isNull(data)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        // 查询今天全量的睡眠数据
        HealthSleepDisplay sleepData =
                healthDataQueryService.queryLatestSleepData(userId, deviceUuid, LocalDateTime.of(data, LocalTime.MIN), LocalDateTime.of(data, LocalTime.MAX));
        if (Objects.isNull(sleepData)) {
            return null;
        }
        return buildSleepDetailVo(sleepData, data);
    }

    /**
     * 构建睡眠详情数据
     * @param sleepData
     * @param data
     * @return
     */
    private SleepDetailVo buildSleepDetailVo(HealthSleepDisplay sleepData, LocalDate data) {
        // 睡眠数据
        SleepDetailVo sleepDetailVo = new SleepDetailVo();
        sleepDetailVo.setDate(data);
        sleepDetailVo.setWeek(WeekDay.parse(data));
        sleepDetailVo.setSleepStartTime(sleepData.getStartTime());
        sleepDetailVo.setSleepEndTime(sleepData.getEndTime());
        // 深度睡眠时长
        Integer deepSleepDuration = sleepData.getDeepSleepDuration();
        sleepDetailVo.setDeepSleepDuration(deepSleepDuration);
        // 浅睡时长
        Integer lightSleepDuration = sleepData.getLightSleepDuration();
        sleepDetailVo.setLightSleepDuration(lightSleepDuration);
        // 快速眼动时长
        Integer rapidEyeMovementDuration = sleepData.getRapidEyeMovementDuration();
        sleepDetailVo.setRapidEyeMovementDuration(rapidEyeMovementDuration);
        // 苏醒时长
        Integer wakeUpDuration = sleepData.getWakeDuration();
        sleepDetailVo.setWakeUpDuration(wakeUpDuration);
        // 睡眠总时长
        int sleepDuration = sleepData.getDuration();
        sleepDetailVo.setSleepDuration(sleepDuration);
        BigDecimal sleepDurationBigDecimal = BigDecimal.valueOf(sleepDuration);
        // 计算深度睡眠占比
        sleepDetailVo.setDeepSleepDurationPercent(BigDecimal.valueOf(deepSleepDuration).divide(sleepDurationBigDecimal, TWO, RoundingMode.HALF_UP));
        // 浅睡占比
        sleepDetailVo.setLightSleepDurationPercent(BigDecimal.valueOf(lightSleepDuration).divide(sleepDurationBigDecimal, TWO, RoundingMode.HALF_UP));
        // 快速眼动占比
        sleepDetailVo.setRapidEyeMovementDurationPercent(BigDecimal.valueOf(rapidEyeMovementDuration).divide(sleepDurationBigDecimal, TWO, RoundingMode.HALF_UP));
        // 清醒占比
        sleepDetailVo.setWakeUpDurationPercent(BigDecimal.valueOf(wakeUpDuration).divide(sleepDurationBigDecimal, TWO, RoundingMode.HALF_UP));
        // 睡眠总得分
        sleepDetailVo.setSleepScore(sleepData.getSleepScore());
        SleepCalculationData sleepCalculationData = JSON.parseObject(sleepData.getRawData(), SleepCalculationData.class);
        if (Objects.nonNull(sleepCalculationData)) {
            // 睡眠阶段
            sleepDetailVo.setSleepSection(ListUtils.map(sleepCalculationData.getSections(), sleepSection -> SleepDetailVo.SleepSectionVo.build(sleepSection.getStart(), sleepSection.getEnd(), sleepSection.getType())));
        }
        return sleepDetailVo;
    }

    @Override
    public WeekSleepDetailVo getWeekSleepDetailData(String deviceUuid, String startTime, String endTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate startDate = DateUtils.parseLocalDate(startTime);
        if (Objects.isNull(startDate)) {
            throw new BusinessException("开始时间格式错误");
        }
        LocalDate endDate = DateUtils.parseLocalDate(endTime);
        if (Objects.isNull(endDate)) {
            throw new BusinessException("结束时间格式错误");
        }
        LocalDateTime start = LocalDateTime.of(startDate, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(endDate, LocalTime.MAX);
        Long userId = UserInfoUtils.getUserId();
        List<HealthSleepDisplay> sleepDataList = healthDataQueryService.querySleepData(userId, deviceUuid, start, end);
        return WeekSleepDetailVo.build(ListUtils.map(sleepDataList, sleepData -> buildSleepDetailVo(sleepData, sleepData.getCreatedAt().toLocalDate())));
    }

    @Override
    public HeartRateDetailVo getHeartRateDetailData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate data = DateUtils.parseLocalDate(dataTime);
        if (Objects.isNull(data)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        LocalDateTime start = LocalDateTime.of(data, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(data, LocalTime.MAX);
        List<HealthHeartRate> heartRateDataList = healthDataQueryService.queryHrData(userId, deviceUuid, start,  end);
        if (CollectionUtils.isEmpty(heartRateDataList)) {
            return new HeartRateDetailVo();
        }
        HeartRateDetailVo heartRateDetailVo = new HeartRateDetailVo();
        List<HeartRateDetailVo.HeartRateData> heartRateList = new ArrayList<>();
        // 最高心率 最低心率 平均心率
        int maxHeartRate = ZERO, minHeartRate = Integer.MAX_VALUE, avgHeartRate = ZERO;
        for (HealthHeartRate heartRateData : heartRateDataList) {
            maxHeartRate = Math.max(maxHeartRate, heartRateData.getMaxBpm());
            minHeartRate = Math.min(minHeartRate, heartRateData.getMinBpm());
            avgHeartRate += heartRateData.getAvgBpm();
            heartRateList.add(HeartRateDetailVo.HeartRateData.build(heartRateData.getRecordedAt(), heartRateData.getAvgBpm()));
        }
        heartRateDetailVo.setMaxHeartRate(maxHeartRate);
        heartRateDetailVo.setMinHeartRate(minHeartRate);
        heartRateDetailVo.setAvgHeartRate(avgHeartRate / heartRateDataList.size());
        heartRateDetailVo.setHeartRateData(heartRateList);
        return heartRateDetailVo;
    }

    @Override
    public BloodPressureDetailDataVo getBloodPressureDetailData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate date = DateUtils.parseLocalDate(dataTime);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        List<HealthBloodPressure> bloodPressureDataList = healthDataQueryService.queryBpData(userId, deviceUuid, start, end);
        if (CollectionUtils.isEmpty(bloodPressureDataList)) {
            return new BloodPressureDetailDataVo();
        }
        List<BloodPressureData> dpDataList = ListUtils.map(bloodPressureDataList, dpData -> {
            // 计算出 血压状态
            BloodPressureStatusEnum status = BloodPressureStatusEnum.parse(dpData.getSystolic(), dpData.getDiastolic());
            // 计算出时间今天的分钟
            int minute = DateUtils.getMinute(dpData.getRecordedAt());
            return BloodPressureData.build(status, minute, dpData.getSystolic(), dpData.getDiastolic());
        });
        return BloodPressureDetailDataVo.build(dpDataList);
    }

    @Override
    public StressValueDetailDataVo getStressValueDetailData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate date = DateUtils.parseLocalDate(dataTime);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        List<HealthHeartRateVariability> stressValueDataList = healthDataQueryService.queryStressValueData(userId, deviceUuid, start, end);
        List<StressValueDetailData> stressValueDetailDataList =
                ListUtils.map(stressValueDataList, hrvData -> StressValueDetailData.build(hrvData.getRecordedAt(), hrvData.getStress()));
        return StressValueDetailDataVo.build(stressValueDetailDataList);
    }

    @Override
    public EcgDetailDataVo getEcgDetailData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate date = DateUtils.parseLocalDate(dataTime);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        List<HealthEcg> ecgDataList = healthDataQueryService.queryEcgData(userId, deviceUuid, start, end);
        if (CollectionUtils.isEmpty(ecgDataList)) {
            return new EcgDetailDataVo();
        }
        List<EcgDetailData> ecgDetailDataList = new ArrayList<>();
        // 根据采集时间进行分组
        Map<LocalDateTime, List<HealthEcg>> recordedAtAndEcgDataMap = ecgDataList.stream().collect(Collectors.groupingBy(HealthEcg::getRecordedAt));
        recordedAtAndEcgDataMap.forEach((recordedAt, ecgDataArr) -> {
            List<Integer> ecgDetailData = ListUtils.flatMapDistinct(ecgDataArr, ecgData -> {
                if (StringUtils.isBlank(ecgData.getRawData())) {
                    return Stream.empty();
                }
                List<Integer> rawData = JSON.parseArray(ecgData.getRawData(), Integer.class);
                return rawData.stream();
            });
            // 分析心电
            HeartEcgDataAnalysisResp resp = algorithmService.heartDataAnalysis(deviceUuid, ecgDataArr);
            log.info("心电分析:{}", resp);
            if (Objects.isNull(resp)) {
                return;
            }
            EcgAnalysisResultEnum status = EcgAnalysisResultEnum.parse(resp.getResult());
            log.info("EcgAnalysisResult:{}", status);
            if (Objects.isNull(status)) {
                return;
            }
            BigDecimal direction = new BigDecimal(resp.getDirection());
            List<BigDecimal> ecgList = EcgHelper.removeBaselineDrift(ListUtils.map(ecgDetailData, ecg -> new BigDecimal(ecg).multiply(direction)), 50);
            ecgDetailDataList.add(EcgDetailData.build(recordedAt.toLocalTime(), resp.getHr(), status, ecgList));
        });
        return EcgDetailDataVo.build(ecgDetailDataList);
    }

    @Override
    public List<Integer> queryExistTraceDate(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        // 获取到当月1号
        LocalDate date = DateUtils.parseLocalDate(dataTime, DateUtils.YYYY_MM);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        // 获取到当月1号 的 00：00：00
        LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN);
        // 获取到当月最后一天 的 23：59：59
        LocalDateTime end = LocalDateTime.of(date.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX);
        List<LocalDateTime> trackDataTimes = healthDataQueryService.queryExistTraceDate(userId, deviceUuid, start, end);
        return ListUtils.mapDistinct(trackDataTimes, LocalDateTime::getDayOfMonth);
    }

    @Override
    public BloodOxygenDetailDataVo getBloodOxygenDetailData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate date = DateUtils.parseLocalDate(dataTime, DateUtils.YYYY_MM_DD);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        List<HealthBloodOxygen> bloodOxygenDataList = healthDataQueryService.queryBloodOxygenData(userId, deviceUuid, start, end);
        if (CollectionUtils.isEmpty(bloodOxygenDataList)) {
            return BloodOxygenDetailDataVo.build(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, new ArrayList<>());
        }
        // 累加血氧值
        BigDecimal sumOxygen = BigDecimal.ZERO;
        // 最低血氧(当天最低)
        BigDecimal lowestBloodOxygen = NumberConstants.BIG_DECIMAL_999999;
        // 最高血氧(当天最高)
        BigDecimal highestBloodOxygen = BigDecimal.ZERO;
        List<BloodOxygenData> bloodOxygenDataArr = new ArrayList<>();
        for (HealthBloodOxygen bloodOxygenData : bloodOxygenDataList) {
            // 忽略无效数据
            if (ObjectUtils.isAnyNull(bloodOxygenData.getAvgOxygen(),
                    bloodOxygenData.getMaxOxygen(), bloodOxygenData.getMinOxygen(), bloodOxygenData.getRecordedAt())) {
                continue;
            }
            sumOxygen = sumOxygen.add(bloodOxygenData.getAvgOxygen());
            if (lowestBloodOxygen.compareTo(bloodOxygenData.getMinOxygen()) > ZERO) {
                lowestBloodOxygen = bloodOxygenData.getMinOxygen();
            }
            if (highestBloodOxygen.compareTo(bloodOxygenData.getMaxOxygen()) < ZERO) {
                highestBloodOxygen = bloodOxygenData.getMaxOxygen();
            }
            BloodOxygenData bloodOxygenDataVo = BloodOxygenData.build(bloodOxygenData.getRecordedAt(), bloodOxygenData.getAvgOxygen());
            bloodOxygenDataArr.add(bloodOxygenDataVo);
        }
        BigDecimal averageBloodOxygen = sumOxygen.divide(new BigDecimal(bloodOxygenDataArr.size()), TWO, RoundingMode.HALF_UP);
        return BloodOxygenDetailDataVo.build(averageBloodOxygen, highestBloodOxygen, lowestBloodOxygen, bloodOxygenDataArr);
    }

    @Override
    public TemperatureDetailDataVo getTemperatureDetailData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate date = DateUtils.parseLocalDate(dataTime, DateUtils.YYYY_MM_DD);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        List<HealthTemperature> temperatureDataList = healthDataQueryService.queryTemperatureData(userId, deviceUuid, start, end);
        if (CollectionUtils.isEmpty(temperatureDataList)) {
            return TemperatureDetailDataVo.build(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, new ArrayList<>());
        }
        BigDecimal sumTemperature = BigDecimal.ZERO;
        // 最低体温(当天最低)
        BigDecimal lowestTemperature = NumberConstants.BIG_DECIMAL_999999;
        BigDecimal highestTemperature = BigDecimal.ZERO;
        List<TemperatureDetailDataVo.TemperatureData> temperatureDataArr = new ArrayList<>();
        for (HealthTemperature temperatureData : temperatureDataList) {
            if (ObjectUtils.isAnyNull(temperatureData.getEstTemp(), temperatureData.getRecordedAt())) {
                continue;
            }
            sumTemperature = sumTemperature.add(temperatureData.getEstTemp());
            if (lowestTemperature.compareTo(temperatureData.getEstTemp()) > ZERO) {
                lowestTemperature = temperatureData.getEstTemp();
            }
            if (highestTemperature.compareTo(temperatureData.getEstTemp()) < ZERO) {
                highestTemperature = temperatureData.getEstTemp();
            }
            temperatureDataArr.add(TemperatureDetailDataVo.TemperatureData.build(temperatureData.getRecordedAt(), temperatureData.getEstTemp()));
        }
        BigDecimal avgTemperature = sumTemperature.divide(new BigDecimal(temperatureDataArr.size()), TWO, RoundingMode.HALF_UP);
        return TemperatureDetailDataVo.build(avgTemperature, highestTemperature, lowestTemperature, temperatureDataArr);
    }

    @Override
    public SportDataDetailVo getSportDataDetail(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate date = DateUtils.parseLocalDate(dataTime, DateUtils.YYYY_MM_DD);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        return buildSportDataDetailVo(deviceUuid, start, end);
    }


    /**
     * 构建运动数据详情
     * @param deviceUuid
     * @param start
     * @param end
     * @return
     */
    private SportDataDetailVo buildSportDataDetailVo(String deviceUuid, LocalDateTime start, LocalDateTime end) {
        Long userId = UserInfoUtils.getUserId();
        List<SportData> sportDataList = healthDataQueryService.querySportData(userId, deviceUuid, start, end);
        if (CollectionUtils.isEmpty(sportDataList)) {
            return SportDataDetailVo.build(new ArrayList<>());
        }
        List<List<SportData>> sportDataListArr = aggregateSportData(sportDataList);
        // 根据运动类型分组
        Map<SportTypeEnum, List<List<SportData>>> sportTypeToDataListMap = ListUtils.groupingBy(ListUtils.filter(sportDataListArr, CollectionUtils::isNotEmpty), arr -> {
            if (CollectionUtils.isEmpty(arr)) {
                return null;
            }
            SportData firstSportData = arr.get(ZERO);
            return SportTypeEnum.parse(firstSportData.getSportType());
        });
        List<SportDataDetail> sportDataDetails = sportTypeToDataListMap.entrySet().stream().map(entry -> {
            // 卡路里 和 距离
            BigDecimal calories = BigDecimal.ZERO, distance = BigDecimal.ZERO;
            Integer duration = ZERO;
            List<SportDataRecord> sportDataRecords = new ArrayList<>();
            for (List<SportData> arr : entry.getValue()) {
                SportData firstSportData = arr.get(ZERO);
                SportData lastSportData = arr.get(arr.size() - ONE);
                // 运动时长
                Integer recordDuration = DateUtils.getTimeBetween(firstSportData.getDataTime(), lastSportData.getDataTime(), TimeUnit.MINUTES);
                // 计算总的运动时长
                duration += recordDuration;
                // 累计卡路里
                BigDecimal recordCalorie = arr.stream().map(data -> data.getCalorie()).collect(Collectors.reducing(BigDecimal.ZERO, BigDecimal::add));
                // 计算总的卡路里
                calories = calories.add(recordCalorie);
                BigDecimal recordDistance = arr.stream().map(data -> data.getDistance()).collect(Collectors.reducing(BigDecimal.ZERO, BigDecimal::add));
                // 累计距离
                distance = distance.add(recordDistance);
                sportDataRecords.add(SportDataRecord.build(recordDistance, recordDuration, recordCalorie, firstSportData.getDataTime(), lastSportData.getDataTime()));
            }
            return SportDataDetail.build(entry.getKey(), distance, duration, calories, sportDataRecords.size(), sportDataRecords);
        }).collect(Collectors.toList());
        return SportDataDetailVo.build(sportDataDetails);
    }

    /**
     * 聚合运动数据
     * @param sportDataList
     * @return
     */
    private List<List<SportData>> aggregateSportData(List<SportData> sportDataList) {
        // 根据时间排序 时间早的在前面
        sportDataList.sort(Comparator.comparing(SportData::getDataTime));
        List<List<SportData>> sportDataListArr = new ArrayList<>();
        List<SportData> sportDataArr = new ArrayList<>();
        sportDataListArr.add(sportDataArr);
        // 上一个运动结束时间
        LocalDateTime previousSportEndTime = null;
        // 上一个运动类型
        SportTypeEnum previousSportType = null;
        for (SportData data : sportDataList) {
            if (data == null || data.getDataTime() == null || data.getDistance() == null) {
                continue; // 跳过无效数据
            }
            if (Objects.nonNull(previousSportEndTime)) {
                long minutes = DateUtils.getTimeBetween(previousSportEndTime, data.getDataTime(), TimeUnit.MINUTES);
                // 间隔时间超过5分钟 累计运动次数
                if (minutes >= CONTINUOUS_SPORT_INTERVAL_TIME || SportTypeEnum.parse(data.getSportType()) != previousSportType) {
                    sportDataArr = new ArrayList<>();
                    sportDataListArr.add(sportDataArr);
                } else {
                    sportDataArr.add(data);
                }
                previousSportEndTime = data.getDataTime();
            } else {
                previousSportEndTime = data.getDataTime();
                previousSportType = SportTypeEnum.parse(data.getSportType());
            }
        }
        return sportDataListArr;
    }

    @Override
    public SportDataDetailVo getSportDataDetailV2(String deviceUuid, String startTime, String endTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate startDate = DateUtils.parseLocalDate(startTime, DateUtils.YYYY_MM_DD);
        if (Objects.isNull(startDate)) {
            throw new BusinessException("时间格式错误");
        }
        LocalDate endDate = DateUtils.parseLocalDate(endTime, DateUtils.YYYY_MM_DD);
        if (Objects.isNull(endDate)) {
            throw new BusinessException("时间格式错误");
        }
        LocalDateTime start = LocalDateTime.of(startDate, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(endDate, LocalTime.MAX);
        return buildSportDataDetailVo(deviceUuid, start, end);
    }

    @Override
    public ActivityDataVo getActivityData(String deviceUuid, String dataTime) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDate date = DateUtils.parseLocalDate(dataTime, DateUtils.YYYY_MM_DD);
        if (Objects.isNull(date)) {
            throw new BusinessException("时间格式错误");
        }
        // 获取用户ID
        Long userId = UserInfoUtils.getUserId();
        LocalDateTime startTime = LocalDateTime.of(date.minusDays(ONE), LocalTime.MAX);
        LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
        // 获取用户今天运动基础健康数据
        HealthBaseData healthBaseData = healthDataQueryService.queryHealthBaseData(userId, deviceUuid, startTime, endTime);
        ActivityDataVo activityData = ActivityDataVo.build(healthBaseData);
        // 查询出运动数据
        List<SportData> sportDataList = ListUtils.filter(healthDataQueryService.querySportData(userId, deviceUuid, startTime, endTime), data -> Objects.nonNull(data.getDataTime()));
        List<StepsStatistics> stepsStatistics = new ArrayList<>(24);
        List<CalorieStatistics> calorieStatistics = new ArrayList<>(24);
        List<ActivityDurationStatistics> durationStatistics = new ArrayList<>(24);
        List<StandTimeStatistics> standTimeStatistics = new ArrayList<>(24);
        // 聚合数据
        Map<Integer, List<SportData>> hourToSportDataMap = ListUtils.groupingBy(sportDataList, data -> data.getDataTime().getHour());
        Set<Integer> hourSet = new HashSet<>();
        for (Map.Entry<Integer, List<SportData>> entry : hourToSportDataMap.entrySet()) {
            List<SportData> arr = entry.getValue();
            if (CollectionUtils.isEmpty(arr)) {
                continue;
            }
            // 活动时长 和 步数
            int duration = ZERO, steps = ZERO;
            LocalDateTime preDataTime = null;
            // 卡路里
            BigDecimal calories = BigDecimal.ZERO;
            for (SportData data : arr) {
                if (data == null || data.getDataTime() == null) {
                    continue;
                }
                Integer stepCount = data.getStepCount();
                // 站立时长
                if (stepCount != null && stepCount > NumberConstants.EIGHTY
                        && !hourSet.contains(entry.getKey())) {
                    hourSet.add(entry.getKey());
                    standTimeStatistics.add(StandTimeStatistics.build(ONE, entry.getKey()));
                }
                // 累加步数
                steps += (stepCount != null ? stepCount : 0);;
                // 累加卡路里
                calories = calories.add(BigDecimalUtils.ofNullable(data.getCalorie()));
                if (preDataTime != null) {
                    long minutes = DateUtils.getTimeBetween(endTime, data.getDataTime(), TimeUnit.MINUTES);;
                    if (minutes < CONTINUOUS_SPORT_INTERVAL_TIME) {
                        duration += minutes;
                    }
                }
                endTime = data.getDataTime();
            }
            durationStatistics.add(ActivityDurationStatistics.build(duration, entry.getKey()));
            stepsStatistics.add(StepsStatistics.build(steps, entry.getKey()));
            calorieStatistics.add(CalorieStatistics.build(calories, entry.getKey()));
        }
        activityData.setStandTimeList(standTimeStatistics);
        activityData.setStepsList(stepsStatistics);
        activityData.setCalorieList(calorieStatistics);
        activityData.setDurationList(durationStatistics);
        // 运动详情数据
        activityData.setDetailVos(buildActivityDataDetailVo(sportDataList));
        return activityData;
    }

    /**
     * 构建运动详情数据
     * @param sportDataList 运动数据
     * @return 运动详情数据
     */
    private List<ActivityDataDetailVo> buildActivityDataDetailVo(List<SportData> sportDataList) {
        log.info("构建运动详情数据:{}", JSON.toJSONString(sportDataList));
        // 聚合运动数据
        List<List<SportData>> aggregateSportData = aggregateSportData(sportDataList);
        log.info("聚合运动数据:{}", JSON.toJSONString(aggregateSportData));
        // 根据运动类型分组
        Map<SportTypeEnum, List<List<SportData>>> sportTypeToDataListMap = ListUtils.groupingBy(ListUtils.filter(aggregateSportData, CollectionUtils::isNotEmpty), arr -> {
            if (CollectionUtils.isEmpty(arr)) {
                return null;
            }
            SportData firstSportData = arr.get(ZERO);
            return SportTypeEnum.parse(firstSportData.getSportType());
        });
        return sportTypeToDataListMap.entrySet().stream().flatMap(entry -> {
            return ListUtils.mapStream(entry.getValue(), arr -> {
                ActivityDataDetailVo activityDataDetailVo = new ActivityDataDetailVo();
                activityDataDetailVo.setSportType(entry.getKey());
                SportData firstSportData = arr.get(ZERO);
                SportData lastSportData = arr.get(arr.size() - ONE);
                // 运动时长
                Integer duration = DateUtils.getTimeBetween(firstSportData.getDataTime(), lastSportData.getDataTime(), TimeUnit.MINUTES);
                // 累计卡路里
                BigDecimal calories = arr.stream().map(data -> data.getCalorie()).collect(Collectors.reducing(BigDecimal.ZERO, BigDecimal::add));
                BigDecimal distance = arr.stream().map(data -> data.getDistance()).collect(Collectors.reducing(BigDecimal.ZERO, BigDecimal::add));
                // 累计步数
                Integer steps = arr.stream().map(data -> data.getStepCount()).collect(Collectors.summingInt(Integer::intValue));
                activityDataDetailVo.setSteps(steps);
                activityDataDetailVo.setDistance(distance);
                activityDataDetailVo.setCalories(calories);
                activityDataDetailVo.setDuration(duration);
                activityDataDetailVo.setStartTime(firstSportData.getDataTime());
                activityDataDetailVo.setEndTime(lastSportData.getDataTime());
                return activityDataDetailVo;
            }).sorted(Comparator.comparing(ActivityDataDetailVo::getStartTime));
        }).sorted(Comparator.comparing(ActivityDataDetailVo::getStartTime)).collect(Collectors.toList());
    }

    @Override
    public WeekActivityDataVo getWeekActivityData(String deviceUuid, String start, String end) {
        if (StringUtils.isBlank(deviceUuid)) {
            throw new BusinessException("设备ID不能为空!");
        }
        LocalDateTime startDate = LocalDateTime.of(DateUtils.parseLocalDate(start, DateUtils.YYYY_MM_DD), LocalTime.MIN);
        if (Objects.isNull(startDate)) {
            throw new BusinessException("时间格式错误");
        }
        LocalDateTime endDate = LocalDateTime.of(DateUtils.parseLocalDate(end, DateUtils.YYYY_MM_DD), LocalTime.MAX);
        if (Objects.isNull(endDate)) {
            throw new BusinessException("时间格式错误");
        }
        Long userId = UserInfoUtils.getUserId();
        List<HealthBaseData> healthBaseData = Optional.ofNullable(healthDataQueryService.queryLastDataList(userId, deviceUuid, startDate, endDate)).orElse(new ArrayList<>());
        WeekActivityDataVo weekActivityData = new WeekActivityDataVo();
        int runTime = ZERO, totalStep = ZERO, standTime = ZERO;
        BigDecimal totalCalorie = BigDecimal.ZERO;
        for (HealthBaseData data : healthBaseData) {
            totalStep += IntegerUtils.ofNullable(data.getStepCount());
            totalCalorie = totalCalorie.add(BigDecimalUtils.ofNullable(data.getCalorie()));
            runTime += IntegerUtils.ofNullable(data.getActivityDuration());
            standTime += IntegerUtils.ofNullable(data.getStandTime());
        }
        weekActivityData.setRunTime(runTime);
        weekActivityData.setTotalStep(totalStep);
        weekActivityData.setTotalCalorie(totalCalorie);
        weekActivityData.setStandTime(standTime);
        // 查询出运动数据
        List<SportData> sportDataList = ListUtils.filter(healthDataQueryService.querySportData(userId, deviceUuid, startDate, endDate), data -> Objects.nonNull(data.getDataTime()));
        List<WeekActivityDataVo.StepsStatistics> stepsStatistics = new ArrayList<>(SEVEN);
        List<WeekActivityDataVo.CalorieStatistics> calorieStatistics = new ArrayList<>(SEVEN);
        List<WeekActivityDataVo.ActivityDurationStatistics> durationStatistics = new ArrayList<>(SEVEN);
        List<WeekActivityDataVo.StandTimeStatistics> standTimeStatistics = new ArrayList<>(SEVEN);
        Set<WeekDay> hourSet = new HashSet<>();
        Map<WeekDay, List<SportData>> weekDayToHealthDataListMap = ListUtils.groupingBy(sportDataList, data -> WeekDay.parse(data.getDataTime()));
        for (Map.Entry<WeekDay, List<SportData>> entry : weekDayToHealthDataListMap.entrySet()) {
            List<SportData> arr = entry.getValue();
            if (CollectionUtils.isEmpty(arr)) {
                continue;
            }
            // 活动时长 和 步数
            int duration = ZERO, steps = ZERO;
            LocalDateTime preDataTime = null;
            // 卡路里
            BigDecimal calories = BigDecimal.ZERO;
            LocalDateTime endTime = null;
            for (SportData data : arr) {
                if (data == null || data.getDataTime() == null) {
                    continue;
                }
                Integer stepCount = data.getStepCount();
                // 站立时长
                if (stepCount != null && stepCount > NumberConstants.EIGHTY
                        && !hourSet.contains(entry.getKey())) {
                    hourSet.add(entry.getKey());
                    standTimeStatistics.add(WeekActivityDataVo.StandTimeStatistics.build(ONE, entry.getKey()));
                }
                // 累加步数
                steps += (stepCount != null ? stepCount : 0);;
                // 累加卡路里
                calories = calories.add(BigDecimalUtils.ofNullable(data.getCalorie()));
                if (preDataTime != null) {
                    long minutes = DateUtils.getTimeBetween(endTime, data.getDataTime(), TimeUnit.MINUTES);;
                    if (minutes < CONTINUOUS_SPORT_INTERVAL_TIME) {
                        duration += minutes;
                    }
                }
                endTime = data.getDataTime();
            }
            durationStatistics.add(WeekActivityDataVo.ActivityDurationStatistics.build(duration, entry.getKey()));
            stepsStatistics.add(WeekActivityDataVo.StepsStatistics.build(steps, entry.getKey()));
            calorieStatistics.add(WeekActivityDataVo.CalorieStatistics.build(calories, entry.getKey()));
        }
        weekActivityData.setStandTimeList(standTimeStatistics);
        weekActivityData.setStepsList(stepsStatistics);
        weekActivityData.setCalorieList(calorieStatistics);
        weekActivityData.setDurationList(durationStatistics);
        // 运动详情数据
        weekActivityData.setDetailVos(buildActivityDataDetailVo(sportDataList));
        return weekActivityData;
    }

    @Override
    public HeartRriDetailDataVo getHeartRriDetailData(String deviceUuid, String dataTime) {
        Long userId = UserInfoUtils.getUserId();
        LocalDate localDate = DateUtils.parseLocalDate(dataTime, DateUtils.YYYY_MM_DD);
        if (Objects.isNull(localDate)) {
            throw new BusinessException("时间格式错误");
        }
        LocalDateTime startDate = LocalDateTime.of(localDate, LocalTime.MIN);
        if (Objects.isNull(startDate)) {
            throw new BusinessException("时间格式错误");
        }
        LocalDateTime endDate = LocalDateTime.of(localDate, LocalTime.MAX);
        if (Objects.isNull(endDate)) {
            throw new BusinessException("时间格式错误");
        }
        List<HealthRri> healthRris = healthDataQueryService.queryRriData(userId, deviceUuid, startDate, endDate);
        if (CollectionUtils.isEmpty(healthRris)) {
            return new HeartRriDetailDataVo();
        }
        HeartRriDataAnalysisResp heartRriDataAnalysisResp = algorithmService.atrialFibrillationDataAnalysis(deviceUuid, healthRris);
        HeartRateResultEnum checkResult = NO_RESULT;
        if (Objects.nonNull(heartRriDataAnalysisResp)) {
            checkResult = HeartRateResultEnum.pares(heartRriDataAnalysisResp.getResult());
        }
        List<Integer> rriList = ListUtils.flatMapDistinct(healthRris, rri -> {
            // 获取原始数据
            List<Integer> rawData = JSON.parseArray(rri.getRawData(), Integer.class);
            return ListUtils.ofNullable(rawData, Stream.empty());
        });
        return HeartRriDetailDataVo.build(checkResult, rriList);
    }
}
